package replicant3.replicant3;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.ReceiverAdapter;
import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
import org.omg.PortableServer.POAPackage.ObjectNotActive;
import org.omg.PortableServer.POAPackage.ServantAlreadyActive;
import org.omg.PortableServer.POAPackage.WrongPolicy;





import Common.RequestMessage;
import Common.Share;



public class server extends ReceiverAdapter{

	public final static String MULTICAST_SEND = "1";
	public final static String MULTICAST_RECV = "2";

	public static final Map<String, String> NameIpTable = new HashMap<String, String>() {
		{
			put("132", "11");
			put("93", "22");
			put("182", "33");
		}
	};

	private Map<String, corbainterface> _ipClient = new HashMap<String, corbainterface>();
	JChannel _channel = null;
	String _userName = System.getProperty("user.name", "n/a");
	
	
	private corbainterface getServer(String[] args, String ip) {
		corbainterface ret = null;
		try {
			ORB orb = ORB.init(args, null);
			String fileName =   "ior" +NameIpTable.get(ip) +".txt";
			BufferedReader br;
			br = new BufferedReader(new FileReader(fileName));
			String ior = br.readLine();
			br.close();
			org.omg.CORBA.Object o = orb.string_to_object(ior);
			ret = corbainterfaceHelper.narrow(o);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return ret;
	}
	
	public void eventLoop() {

		while (true) {
		}
	}
	
	
	private String getResult(List<String> paras) {
		if (paras.get(0).equals(RequestMessage.CREATE)) {
			if (paras.size() >= 7) {
				String ip = getPrefixIp(paras.get(6));
				if (_ipClient.containsKey(ip)) {
					corbainterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.createPlayerAccount(paras.get(1), paras.get(2), paras.get(3), paras.get(4), paras.get(5), paras.get(6));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.SIGNIN)) {
			if (paras.size() >= 4) {
				String ip = getPrefixIp(paras.get(3));
				if (_ipClient.containsKey(ip)) {
					corbainterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.playerSignIn(paras.get(1), paras.get(2), paras.get(3));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.SIGNOUT)) {
			if (paras.size() >= 3) {
				String ip = getPrefixIp(paras.get(2));
				if (_ipClient.containsKey(ip)) {
					corbainterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.playerSignOut(paras.get(1), paras.get(2));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.STATUS)) {
			if (paras.size() >= 4) {
				String ip = getPrefixIp(paras.get(3));
				if (_ipClient.containsKey(ip)) {
					corbainterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.getPlayerStatus(paras.get(1), paras.get(2), paras.get(3));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.SUSPEND)) {
			if (paras.size() >= 5) {
				String ip = getPrefixIp(paras.get(3));
				if (_ipClient.containsKey(ip)) {
					corbainterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.suspendAccount(paras.get(1), paras.get(2), paras.get(3),paras.get(4));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.TRANSFER)) {
			if (paras.size() >= 5) {
				String ip = getPrefixIp(paras.get(3));
				if (_ipClient.containsKey(ip)) {
					corbainterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.transferAccount(paras.get(1), paras.get(2), paras.get(3),paras.get(4));
					}
				}
			}
		}

		return "0";
	}
	
	private String getPrefixIp(final String ip) {
		int index = ip.indexOf(".");
		return ip.substring(0, index);
	}
	
	public void receive(Message msg) {
		// String line=msg.getSrc() + ":receiver: " + msg.getObject();
		String line = msg.getObject().toString();
		System.out.println("receive multi-cast message:"+line);
		List<String> resu = Arrays.asList(line.split(Share.DELIMETER));
		if (resu.get(0).equals(MULTICAST_SEND)) {
			List<String> resu1 = resu.subList(1, resu.size()-1);
			String result = getResult(resu1);
			String multiMessage = MULTICAST_RECV + Share.DELIMETER
					+ "replicant3"+ Share.DELIMETER + result + Share.DELIMETER;
			Message resultmsg = new Message(null, null, multiMessage);
			try {
				_channel.send(resultmsg);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

	public void start(final String[] args) {

		try {

			new Thread(new Runnable() {
				public void run() {
					
						try {
							startCorba(args);
						} catch (InvalidName | ServantAlreadyActive
								| WrongPolicy | ObjectNotActive
								| FileNotFoundException | AdapterInactive
								| RemoteException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					
				}
			}).start();

			_channel = new JChannel();
			_channel.setReceiver(this);
			_channel.connect("ServerCluster");

			_ipClient.put("132", getServer(args, "132"));
			_ipClient.put("93", getServer(args, "93"));
			_ipClient.put("182", getServer(args, "182"));
			eventLoop();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
		}

		if (_channel != null) {
			_channel.close();
		}
	}

	/**
	 * @param args
	 * @throws InvalidName
	 * @throws ServantAlreadyActive
	 * @throws WrongPolicy
	 * @throws ObjectNotActive
	 * @throws FileNotFoundException
	 * @throws AdapterInactive
	 * @throws RemoteException
	 */

	private void startCorba(String[] args) throws InvalidName,
			ServantAlreadyActive, WrongPolicy, ObjectNotActive,
			FileNotFoundException, AdapterInactive, RemoteException {

		ORB orb = ORB.init(args, null);
		POA rootPOA = POAHelper.narrow(orb
				.resolve_initial_references("RootPOA"));
		replica_pratik North = new replica_pratik(5789);
		byte[] id11 = rootPOA.activate_object(North);
		org.omg.CORBA.Object ref11 = rootPOA.id_to_reference(id11);

		String ior11 = orb.object_to_string(ref11);
		PrintWriter file1 = new PrintWriter("ior11.txt");
		file1.println(ior11);
		file1.close();

		replica_pratik Europe = new replica_pratik(5799);
		byte[] id2 = rootPOA.activate_object(Europe);
		org.omg.CORBA.Object ref2 = rootPOA.id_to_reference(id2);

		String ior2 = orb.object_to_string(ref2);
		PrintWriter file2 = new PrintWriter("ior22.txt");
		file2.println(ior2);
		file2.close();

		replica_pratik Asia = new replica_pratik(6000);
		byte[] id3 = rootPOA.activate_object(Asia);
		org.omg.CORBA.Object ref3 = rootPOA.id_to_reference(id3);

		String ior3 = orb.object_to_string(ref3);
		PrintWriter file3 = new PrintWriter("ior33.txt");
		file3.println(ior3);
		file3.close();
		System.out.println("Working");

		(new UDP("NA", 5789, North)).start();
		(new UDP("EU", 5799, Europe)).start();
		(new UDP("AS", 6000, Asia)).start();

		rootPOA.the_POAManager().activate();
		orb.run();

	}

	public static void main(String[] args) {
		new server().start(args);

	}

}
